﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Game
{
    class AI
    {
        const int Max_Astar_Num = 7;
        List<Dictionary<string, int>> _AtkResult;
        UI _UI;
        Map _MyMap;
        Player _P1, _P2;
        const int Category = 3;
        NeuralNetwork _nnw;
        public List<Dictionary<string, int>> AtkAction {
            get { return _AtkResult; }
        }

        public AI(UI ui, int turn)
        {
            _AtkResult = new List<Dictionary<string,int>>();
            _UI = ui;
            _MyMap = ui.Map;
            _P1 = ui.GetPlayer(turn);
            _P2 = ui.GetPlayer(turn ^ 1);
            _nnw = new NeuralNetwork() ;
        }
     
        public bool Run()
        {
            _AtkResult.Clear();
            Schedule();
            RestAll();
            return true;
        }

        void RestAll() {
            for (int i = 0; i < _P1.Slimes.Count; i++)
            {
                _P1.Slimes[i].Stay();
            }
        }
        int CallNeuralNetwork() {
            int sum1 = 0;
            int sum2 = 0;
            for (int i = 0; i < _P1.Slimes.Count; i++)
            {
               sum1 += _P1.Slimes[i].HP;
            }
            for (int i = 0; i < _P2.Slimes.Count; i++)
            {
                sum2 += _P2.Slimes[i].HP;
            }
            /*Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11}", _P2.Slimes[0].HP, sum1, _P2.EachCount(SlimesCategory.PAWN), _P2.EachCount(SlimesCategory.ARCHER), _P2.EachCount(SlimesCategory.KNIGHT),
                                  _P1.Slimes[0].HP, sum2, _P1.EachCount(SlimesCategory.PAWN), _P1.EachCount(SlimesCategory.ARCHER), _P1.EachCount(SlimesCategory.KNIGHT),
                                  ActionSet.TestATK(_UI, _P1.Side), ActionSet.TestATK(_UI, _P2.Side));*/

            int answer = _nnw.RunNeuralNetwork(_P2.Slimes[0].HP, sum1, _P2.EachCount(SlimesCategory.PAWN), _P2.EachCount(SlimesCategory.ARCHER), _P2.EachCount(SlimesCategory.KNIGHT),
                                  _P1.Slimes[0].HP, sum2, _P1.EachCount(SlimesCategory.PAWN), _P1.EachCount(SlimesCategory.ARCHER), _P1.EachCount(SlimesCategory.KNIGHT),
                                  ActionSet.TestATK(_UI,_P1.Side),ActionSet.TestATK(_UI,_P2.Side));
            /*Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11}", _P2.Slimes[0].HP, sum1, _P2.EachCount(SlimesCategory.PAWN), _P2.EachCount(SlimesCategory.ARCHER), _P2.EachCount(SlimesCategory.KNIGHT),
                                  _P1.Slimes[0].HP, sum2, _P1.EachCount(SlimesCategory.PAWN), _P1.EachCount(SlimesCategory.ARCHER), _P1.EachCount(SlimesCategory.KNIGHT),
                                  ActionSet.TestATK(_UI, _P1.Side), ActionSet.TestATK(_UI, _P2.Side));*/

           return answer;
        }
        void Schedule()
        {
            List<ACTION_MODE> act = new List<ACTION_MODE>();
            ACTION_MODE tempaction = ACTION_MODE.ATK_MODE;
            switch (CallNeuralNetwork())
            {
                case 1:
                    tempaction = ACTION_MODE.ATK_MODE;
                    break;
                case 2:
                    tempaction = ACTION_MODE.DEF_MODE;
                    break;
                default:
                    break;
            }            
            for (int i = 0; i <  _P1.Slimes.Count; i++) {
                act.Add(tempaction); 
            }
            List<int> order;
            if (_P1.Slimes.Count > Max_Astar_Num)
            {
                SlimeGame temp = new SlimeGame(_UI.GameData);
                Scheduler GA = new Scheduler(temp.GetUI(), _P1.Side, act);
                GA.Run();
                order = GA.Order;
            }else{
                SlimeGame temp = new SlimeGame(_UI.GameData);
                Scheduler_AStar Astar = new Scheduler_AStar(temp.GetUI(), _P1.Side, act);
                Astar.Run();
                order = Astar.Order;            
            }


            //暫時寫在這
            //暫時寫在這
            //暫時寫在這
            //暫時寫在這
            
            Slime S0 = _P1.Slimes[0];

            if (!S0.Hited && S0.HP > S0.MaxHP/2)
            {               // 生產狀態 大史優先生產 在來才考慮逃跑+回血
                char C = 'K';
                if (_P1.EachCount(SlimesCategory.KNIGHT) <= _P1.EachCount(SlimesCategory.ARCHER))
                {
                    C = 'K';
                }
                else if (_P1.EachCount(SlimesCategory.KNIGHT) > _P1.EachCount(SlimesCategory.ARCHER))
                {
                    C = 'A';
                }

                int trying = 0;
                List<Position> L = new List<Position>();
                L.Add(new Position(S0.Pos.X + 1, S0.Pos.Y));
                L.Add(new Position(S0.Pos.X - 1, S0.Pos.Y));
                L.Add(new Position(S0.Pos.X, S0.Pos.Y + 1));
                L.Add(new Position(S0.Pos.X, S0.Pos.Y - 1));
                while (S0.Active && trying < 4)
                {
                    Position P = L[trying];
                    if (_MyMap.Isin(P))
                    {
                        _UI.Born(C, P);
                    }
                    ++trying;
                }

            }
             
            //暫時寫在這
            //暫時寫在這
            //暫時寫在這
            //暫時寫在這
            Dictionary<string, int> tempDic; 
            for (int i = 0; i < order.Count; i++)
            {   
                tempDic = ActionSet.DoAction(_P1.Slimes[order[i]], _UI, act[order[i]], _P1.Side, true);
                _AtkResult.Add(tempDic);
            }
        }
        
    }
}
